#include <bits/stdc++.h>
namespace scd {
using namespace std;
template <typename Raw = int, typename T = decay_t<Raw>>
inline auto read() -> enable_if_t<is_integral<T>::value, T> {
    T x = 0;
#ifdef USE_IOSTREAM
    cin >> x;
#else
    bool fl = false;
    char c = getchar();
    while (c < '0' || c > '9')
        fl |= (c == '-'), c = getchar();
    while (c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    return fl ? -x : x;
#endif
    return x;
}
template <typename Raw, typename T = decay_t<Raw>>
inline auto read() -> enable_if_t<!is_integral<T>::value, T> {
    T x;
    cin >> x;
    return x;
}
template <typename Raw, typename T = decay_t<Raw>>
inline auto read(Raw&& x) -> enable_if_t<is_integral<T>::value> {
#ifdef USE_IOSTREAM
    cin >> x;
#else
    x = 0;
    bool fl = false;
    char c = getchar();
    while (c < '0' || c > '9')
        fl |= (c == '-'), c = getchar();
    while (c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
#endif
}
inline void read(char* p) {
#ifdef USE_IOSTREAM
    cin >> p;
#else
    char c = getchar();
    while (isspace(c))
        c = getchar();
    while (c != EOF && !isspace(c)) {
        *p++ = c;
        c = getchar();
    }
    *p = '\0';
#endif
}
template <typename T>
inline auto read(T&& x) -> enable_if_t<!is_integral<decay_t<T>>::value> {
    cin >> x;
}
template <typename... T>
inline void read(T&&... x) {
    (read(forward<T>(x)), ...);
}
template <typename Raw = int, typename T = decay_t<Raw>>
inline auto print(Raw x) -> enable_if_t<is_integral<T>::value> {
#ifdef USE_IOSTREAM
    cout << x;
#else
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
#endif
}
template <int d = 6, typename Raw = double, typename T = decay_t<Raw>>
inline auto print(Raw x) -> enable_if_t<is_floating_point<T>::value> {
#ifdef USE_IOSTREAM
    cout.precision(d);
    cout << std::fixed << x;
#else
    printf("%.*f", d, x);
#endif
}
inline void print(char x) {
#ifdef USE_IOSTREAM
    cout.put(x);
#else
    putchar(x);
#endif
}
inline void print(const char* x) {
#ifdef USE_IOSTREAM
    cout << x;
#else
    while (*x)
        putchar(*x++);
#endif
}
template <typename Raw, typename T = decay_t<Raw>>
inline auto print(Raw&& x)
    -> enable_if_t<!is_integral<T>::value && !is_floating_point<T>::value> {
    cout << x;
}
template <typename... T>
inline void print(T&&... x) {
    (print(forward<T>(x)), ...);
}
template <typename... T>
inline void printws(T&&... x) {
    (print(forward<T>(x), ' '), ...);
}
template <typename... T>
inline void println(T&&... x) {
    printws(x...);
    print('\n');
}
}  // namespace scd
using namespace scd;
constexpr uint64_t _Mod_Num = 998244353;
inline auto qpow(uint64_t x, uint64_t k) {
    uint64_t res = 1;
    while (k) {
        if (k & 1)
            res = res * x % _Mod_Num;
        x = x * x % _Mod_Num;
        k >>= 1;
    }
    return res;
}
inline auto inv(uint64_t x) {
    return qpow(x, _Mod_Num - 2);
}
int32_t main(int32_t argc, const char** argv) {
    // freopen("c.in", "r", stdin);
    // freopen("c.out", "w", stdout);
    int _Type = read();
    size_t _N, _M, _Qnum;
    read(_N, _M, _Qnum);
    vector<int> _arr;
    int _Lst_ans = 0;
    while (_Qnum--) {
        int op = read();
        auto x = read<size_t>();
        if (_Type)
            x ^= _Lst_ans;
        if (op == 1)
            _arr.push_back(x);
        else {
            vector<pair<int, int>> __temp_q;
            int __pos = 0;
            auto _Min_X = min(x, _M);
            for (int i : _arr) {
                __temp_q.emplace_back(i, __pos);
                if (++__pos == x)
                    break;
            }
            uint64_t __sum = 1;
            set<pair<int, int>> _Q_now, _Q_other;
            sort(begin(__temp_q), end(__temp_q), greater<>());
            auto _Tq_it = begin(__temp_q);
            auto _Tq_size = __temp_q.size();
            for (int i = 0; i < min(_Min_X, _Tq_size); ++i) {
                __sum = __sum * _Tq_it->first % _Mod_Num;
                _Q_now.insert(*_Tq_it++);
            }
            while (_Tq_it != end(__temp_q))
                _Q_other.insert(*_Tq_it++);
            auto __Res = __sum;
            const auto _Arr_size = _arr.size();
            for (int i = x; i < _Arr_size; ++i) {
                if (auto _It = _Q_now.find({_arr[i - x], i - x});
                    _It != end(_Q_now)) {
                    __sum = __sum * inv(_It->first) % _Mod_Num;
                    _Q_now.erase(_It);
                } else if (auto _It = _Q_other.find({_arr[i - x], i - x});
                           _It != end(_Q_other))
                    _Q_other.erase(_It);
                if (_Q_now.empty()) {
                    _Q_now.emplace(_arr[i], i);
                    __sum = __sum * _arr[i] % _Mod_Num;
                } else if (begin(_Q_now)->first <= _arr[i]) {
                    __sum = __sum * inv(begin(_Q_now)->first) % _Mod_Num;
                    _Q_other.insert(*begin(_Q_now));
                    _Q_now.erase(begin(_Q_now));
                    _Q_now.emplace(_arr[i], i);
                    __sum = __sum * _arr[i] % _Mod_Num;
                } else
                    _Q_other.emplace(_arr[i], i);
                if (_Q_now.size() < _Min_X) {
                    __sum = __sum * _Q_other.rbegin()->first % _Mod_Num;
                    _Q_now.insert(*rbegin(_Q_other));
                    _Q_other.erase(--end(_Q_other));
                }
                __Res = (__Res + __sum) % _Mod_Num;
            }
            println(__Res);
            _Lst_ans = __Res;
        }
    }
    return 0;
}